package com.java.bytebuddy;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassReloadingStrategy;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

/**
 * @author dushougudu
 */
public class Example {

    public void createNewClassWithStaticMethod() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        DynamicType.Unloaded unloaded = new ByteBuddy()
                .subclass(Object.class)
                .name("Demo")
                .defineMethod("fakeStatic", String.class, Modifier.PUBLIC + Modifier.STATIC)
                .withParameter(String.class, "arg")
                .intercept(MethodDelegation.to(MockClass.class))
                .make();
        Object o = unloaded.load(getClass().getClassLoader()).getLoaded().newInstance();
        System.out.println(o.getClass().getMethod("fakeStatic", String.class).invoke(o, "fakeStatic"));
    }


    public void createFromClass() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        DynamicType.Unloaded unloaded = new ByteBuddy()
                .subclass(MockClass.class)
                .name("FakeTest")
                .method(ElementMatchers.hasMethodName("fakeMethod"))
                .intercept(MethodDelegation.to(MockClass.class))
                .make();
        Object o = unloaded.load(getClass().getClassLoader()).getLoaded().newInstance();
        System.out.println(o.getClass().getMethod("fakeMethod", String.class).invoke(o, "fakeMethod"));
    }

    public void createFromClassWithAnnotation() throws Exception {
        DynamicType.Unloaded unloaded = new ByteBuddy()
                .subclass(MockClass.class)
                .name("FakeTest1")
                .method(ElementMatchers.hasMethodName("fakeMethod"))
                .intercept(MethodDelegation.to(MockClass.class))
//                .annotateMethod(AnnotationDescription.Builder.ofType(ApiAnnotation.class).define("author", "dushougudu").build())
                .make();
        for (Annotation annotation : unloaded.load(getClass().getClassLoader()).getLoaded().getAnnotations()) {
            System.out.println(annotation.toString());
        }
    }

    public static void redefineClass() {
        ByteBuddyAgent.install();
        new ByteBuddy().redefine(MockClass.class)
                .method(ElementMatchers.named("fakeMethod"))
                .intercept(FixedValue.value("拦截操作"))
                .make()
                .load(Thread.currentThread().getContextClassLoader(), ClassReloadingStrategy.fromInstalledAgent());

    }

}
